package cli

import (
	"encoding/json"
	"fmt"
	block "github.com/corgi-kx/blockchain_golang/blc"
	"github.com/corgi-kx/blockchain_golang/database"
	"github.com/corgi-kx/blockchain_golang/util"
	"time"
)

var poissonChan = make(chan bool, 1)
var fixTimeChan = make(chan bool, 1)
var eMoney = 100

func (cli Cli) transferTest(lambda float64) {
	//等待启动
	time.Sleep(time.Second * 3)
	fmt.Println("===============开始进行转账测试==============")
	fmt.Printf("泊松过程强度为：%v\n", lambda)
	fmt.Printf("第一步：导入水龙头助记词:%v\n", database.TestWalletWords)

	mnemonicwords := []string{}
	err := json.Unmarshal([]byte(database.TestWalletWords), &mnemonicwords)
	if err != nil {
		fmt.Printf("[%v] 水龙头助记词错误", time.Now().Format("2006-01-02T 15:04:05"))
		return
	}
	bd := database.New()
	wallets := block.NewWallets(bd)
	firstAddress, _, _ := wallets.GenerateWallet(bd, block.CreateBitcoinKeysByMnemonicWord, mnemonicwords)
	fmt.Printf("[%v] 生成水龙头地址:%s\n", time.Now().Format("2006-01-02T 15:04:05"), firstAddress)

	fmt.Printf("第二步：生成测试地址\n")
	//获取所有的地址
	addressList := block.GetAllAddress(bd)
	//测试地址条数需要大于等于100
	if len(*addressList) <= 101 {
		fmt.Printf("[%v] 测试地址条目不够，重新生成地址\n", time.Now().Format("2006-01-02T 15:04:05"))
		for i := 0; i < 100; i++ {
			wallets.GenerateWallet(bd, block.NewBitcoinKeys, []string{})
		}
	}
	addressList = block.GetAllAddress(bd)
	//转出地址
	var outAddressList []string
	//转入地址
	var inAddressList []string

	index := 1
	for _, v := range *addressList {
		if string(v) != firstAddress && index <= 50 {
			outAddressList = append(outAddressList, string(v))
			index++
		} else if string(v) != firstAddress && index <= 100 && index > 50 {
			inAddressList = append(inAddressList, string(v))
			index++
		} else if index > 100 {
			break
		}
	}

	fmt.Printf("[%v] 转出地址列表 %v\n", time.Now().Format("2006-01-02T 15:04:05"), outAddressList)
	fmt.Printf("[%v] 转入地址列表 %v  类型%T\n,", time.Now().Format("2006-01-02T 15:04:05"), inAddressList[0], inAddressList)

	fmt.Printf("第三步：水龙头地址转账到转出地址\n")

	//for ;; {
	//	time.Sleep(time.Duration(util.GeneratePoissonTime(lambda)*1000000000)*time.Nanosecond)
	//	//i := rand.Intn(5)
	//
	//	fmt.Printf("from %v to %v amount %v\n","[\""+firstAddress+"\"]","[\""+outAddressList[1]+"\"]","[1]")
	//	cli.transfer("[\""+firstAddress+"\"]","[\""+inAddressList[i]+"\"]","[1]")
	//}
	go cli.poissonTimeTick(lambda)
	go cli.fixTimeTick(lambda)

	var inAt = 0
	for {
		select {
		//泊松时间触发事件
		case <-poissonChan:
			fmt.Printf("from %v to %v amount %v\n", "[\""+outAddressList[inAt]+"\"]", "[\""+inAddressList[inAt]+"\"]", "[1]")
			cli.transfer("[\""+outAddressList[inAt]+"\"]", "[\""+inAddressList[inAt]+"\"]", "[1]")
			inAt++
			if inAt >= 50 {
				inAt = 0
			}
		//固定时间触发，从水龙头地址中转账
		case <-fixTimeChan:
			cli.transferToOutAddress(firstAddress, eMoney, outAddressList)
		}
	}

}

func (cli Cli) poissonTimeTick(lambda float64) {
	for {
		time.Sleep(time.Duration(util.GeneratePoissonTime(lambda)*1000000000) * time.Nanosecond)
		poissonChan <- true
	}
}

func (cli Cli) fixTimeTick(lambda float64) {
	for {
		fixTimeChan <- true
		t := time.Duration(float64(eMoney*25) * lambda)
		time.Sleep(time.Second * t)
	}
}

func (cli Cli) transferToOutAddress(firstAddress string, money int, toSlice []string) {
	fromSlice := []string{}
	amountSlice := []int{}
	for i := 0; i < 50; i++ {
		fromSlice = append(fromSlice, firstAddress)
		amountSlice = append(amountSlice, money)
	}
	b, _ := json.Marshal(fromSlice)
	fromSliceString := string(b)

	m, _ := json.Marshal(amountSlice)
	amountSliceString := string(m)

	c, _ := json.Marshal(toSlice)
	toSliceString := string(c)

	cli.transfer(fromSliceString, toSliceString, amountSliceString)

}
